﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using DevExpress.Xpo;
using DevExpress.Xpo.DB;
using KamLib;

namespace KamLib
{
    public interface IXpoSessionContainer
    {
        UnitOfWork Session { get; set; }
    }


    /// <summary>
    /// игнорировать [свойства] при копировании данных в Entity
    /// </summary>
    public class ReadOnlyAttribute : Attribute { }

    public static class EntityHelper
    {

        public static bool SetProperty<TEntity>(this TEntity entity, string name, Func<object> value, IEnumerable<ConvertAttribute> converters)
            where TEntity : XPLiteObject
        {
            var m = entity.ClassInfo.FindMember(name);
            if ((m == null || m.IsReadOnly) && name.EndsWith("ID"))
                m = entity.ClassInfo.FindMember(name.Left(name.Length - 2));
            if (m == null || m.IsReadOnly || m.IsIdentity) return false;

            var pdest = entity.GetType().GetPropertyOrField(name);
            var v = value();
            if (converters != null)
            {
                foreach (var convert in converters)
                {
                    if (convert.DataToEntity(entity, pdest, v)) break;
                }
            }

            m.SetValue(entity, m.IsAssociation
                ? entity.Session.GetObjectByKey(m.MemberType, v.To(entity.ClassInfo.KeyProperty.MemberType))
                : v.To(m.MemberType)
            );

            return true;
        }

        public static void CopyFrom<TSource, TEntity>(this TEntity entity, TSource src)
            where TEntity : XPLiteObject
        {
            foreach (var psrc in src.GetType().GetPropertiesAndFields())
            {
                if (psrc.HasAttribute<ReadOnlyAttribute>()) continue;
                entity.SetProperty(psrc.Name, () => psrc.GetValue(src, null), psrc.GetAttributes<ConvertAttribute>());
            }
        }

        public static void CopyFrom<TEntity>(this TEntity entity, Dictionary<string, object> src)
            where TEntity : XPLiteObject
        {
            foreach (var psrc in src)
            {
                entity.SetProperty(psrc.Key, () => psrc.Value, null);
            }
        }



        public static PropertyInfo[] GetKeyFields<TEntity>()
            where TEntity : class
        {
            return typeof(TEntity).GetProperties().Where(a => a.HasAttribute<KeyAttribute>()).ToArray();
        }
    }
}